package com.sushengren.easyword;

import com.sushengren.easyword.anchor.PlaceholderAnchor;
import com.sushengren.easyword.constants.DefaultAnchors;
import com.sushengren.easyword.constants.DefaultHandles;
import com.sushengren.easyword.converters.BeanConverter;
import com.sushengren.easyword.exception.IORuntimeException;
import com.sushengren.easyword.handle.AnchorHandle;
import com.sushengren.easyword.handle.WriteDataNormalizeHandle;
import com.sushengren.easyword.model.AnchorContext;
import com.sushengren.easyword.model.WriteData;
import com.sushengren.easyword.util.FileUtil;
import com.sushengren.easyword.util.IoUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import java.io.*;
import java.util.List;

/**
 * Word 操作入口类
 *
 * @author sushengren
 */
public class EasyWord {

    /**
     * 通过模板文件构建
     *
     * @param file 模板文件
     * @return {@link Builder}
     */
    public static Builder of(File file) {
        return of(IoUtil.toStream(file));
    }

    /**
     * 通过模板文件构建
     *
     * @param in 模板文件输入流
     * @return {@link Builder}
     */
    public static Builder of(InputStream in) {
        return new Builder(in);
    }

    public static class Builder {

        private InputStream inputStream;
        private XWPFDocument document;

        Builder(InputStream inputStream) {
            builder(inputStream);
        }

        private void builder(InputStream inputStream) {
            this.inputStream = inputStream;
            try {
                document = new XWPFDocument(inputStream);
            } catch (IOException e) {
                throw new IORuntimeException("解析文档异常", e);
            } finally {
                IoUtil.close(inputStream);
            }
        }

        public Builder doWrite(Object data) {
            return doWrite(BeanConverter.beanToWriteData(data));
        }

        @SuppressWarnings("ResultOfMethodCallIgnored")
        public Builder doWrite(List<WriteData> dataList) {
            WriteDataNormalizeHandle.normalize(dataList);

            List<AnchorHandle> defaultHandles = DefaultHandles.getDefaultHandles();
            List<AnchorContext> bookmarkAnchor = DefaultAnchors.BOOKMARK_ANCHOR.locate(document);
            anchorHandle(bookmarkAnchor, defaultHandles, dataList);

            if (!CollectionUtils.isEmpty(bookmarkAnchor)) {
                try {
                    File tempFile = FileUtil.createTempFile("EasyWord-", null, FileUtil.getTmpDir(), true);
                    toOutputStream(new FileOutputStream(tempFile));
                    builder(new FileInputStream(tempFile));
                    tempFile.delete();
                } catch (FileNotFoundException e) {
                    throw new IllegalArgumentException(e);
                }
            }

            List<AnchorContext> placeholderAnchor = DefaultAnchors.PLACEHOLDER_ANCHOR.locate(document);
            anchorHandle(placeholderAnchor, defaultHandles, dataList);
            return this;
        }

        private void anchorHandle(List<AnchorContext> anchorContextList, List<AnchorHandle> anchorHandleList, List<WriteData> dataList) {
            for (AnchorContext anchor : anchorContextList) {
                for (AnchorHandle defaultHandle : anchorHandleList) {
                    String firstKey = anchor.getKey().split(PlaceholderAnchor.FLAG_SPLIT)[0];
                    WriteData writeData = dataList.stream().filter(date -> date.getKey().equals(firstKey)).findFirst().orElse(null);
                    defaultHandle.handle(anchor, writeData);
                }
            }
        }

        /**
         * 用流的方式输出文档，此方法会关闭流
         *
         * @param os 输出流
         */
        public void toOutputStream(OutputStream os) {
            try {
                document.write(os);
            } catch (IOException e) {
                throw new IORuntimeException("输出文档异常", e);
            } finally {
                IoUtil.close(os);
                IoUtil.close(inputStream);
                IoUtil.close(document);
            }
        }

    }

}
